package 多线程.三个线程实现顺序打印;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同：
 * CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行
 * CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行
 * CountDownLatch是不能够重用的,而CyclicBarrier是可以重用的(主要区别)
 *
 * CyclicBarrier的两个特性
 * 栅栏：多个线程相互等待，到齐后再执行特定动作
 * 循环：所有线程释放后，还能继续复用它
 * 这道题怎么用CyclicBarrier解决呢？
 * 线程B和线程C需要使用栅栏等待
 * 为了让B和C也顺序执行，需要用一个状态，来标识应该执行的线程
 * 当然, CyclicBarrier的实现其实还是基于lock + condition,
 * 多个线程在到达一定条件前await,到达条件后signalAll
 */
public class Test7 {
    /**
     * 构造方法的作用：
     * 创建一个CyclicBarrier,当给定数量的线程在等待它时,它将被绊倒,此时它不执行预定义的操作
     * parties：在CyclicBarrier的实例被触发之前必须调用等待的线程数
     * await()：等到数量为parties的所有线程都到达指定的临界点
     */
    private static CyclicBarrier cyclicBarrier = new CyclicBarrier(1);
    private static Integer state = 1;
    public static void main(String[] args) {
        Test7 t = new Test7();
        Thread t1 = new Thread() {
            @Override
            public void run() {
                t.printA();
            }
        };
        Thread t2 = new Thread() {
            @Override
            public void run() {
                try {
                    t.printB();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        Thread t3 = new Thread() {
            @Override
            public void run() {
                try {
                    t.printC();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        t1.start();
        t2.start();
        t3.start();
    }

    public void printA(){
        while (state != 1){
        }
        System.out.println("A");
        state = 2;
    }

    public void printB() throws InterruptedException{
        try {
            cyclicBarrier.await();
            //state不等于2的时候等待
            while (state != 2) {
            }
            System.out.println("B");
            state = 3;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }

    public static void printC() throws InterruptedException {
        try {
            cyclicBarrier.await();
            while (state != 3) {
            }
            System.out.println("C");
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}
